/*******************************************************************
 *
 * @Version : 0.5 
 *
 * Monster.java 
 *
 * 2011-10-11 下午01:50:22
 *
 *******************************************************************/
package game.breeze.gameserver.controller;

import game.breeze.astar.AStarNode;
import game.breeze.data.GameObject;
import game.breeze.math.Position;
import game.breeze.resource.GameObjectDef;
import game.breeze.resource.MonsterDef;
import game.breeze.socket.util.ByteBuffer;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang.math.RandomUtils;

/**
 * Class desc there
 * 
 * @author yangwei ywengineer@gmail.com
 * 
 */
public class MonsterController extends GameObject {
	// 父容器
	private GameMapController mapController;
	// 怪物数据
	private MonsterDef monsterDef;
	// 原始坐标
	private Position original;
	// 死亡状态
	private boolean dead;
	// 上一次移动时间
	private float premove;
	// 移动速度
	private float speed;
	// 移动坐标
	private final List<Position> positions = new ArrayList<Position>();
	// 移动路径
	private LinkedList<AStarNode> paths = new LinkedList<AStarNode>();

	public MonsterController(GameMapController p, GameObjectDef def) {
		super(def);
		this.mapController = p;
		monsterDef = (MonsterDef) def;
		speed = monsterDef.getMoveSpeed() * 1.0f / 1000;
	}

	/**
	 * 能否攻击坐标
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public boolean canAttack(int x, int y) {
		return Math.sqrt(Math.pow(Math.abs(getX() - x), 2) + Math.pow(Math.abs(this.getY() * 1.0d - y), 2)) <= monsterDef.getAttackRegion();
	}

	/**
	 * 能否移动
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public boolean canMove(int x, int y) {
		// return moveRect.contains(x, y);
		return true;
	}

	/**
	 * 根据移动速度判断是否可以移动.停留时间是否足够
	 * 
	 * @param delta
	 *            运行时间
	 * @return 是否可移动
	 */
	public boolean canMove(float delta) {
		// 是否有路径可以移动
		// 是否到达移动速度
		boolean isSpeed = delta - premove >= speed;
		boolean move = isSpeed && paths.size() > 0;
		// 可以移动
		if (move) {
			// 重置移动时间
			premove = delta;
		} else if (paths.size() == 0) {// 没有路径.是否达到停留时间
			move = isSpeed;
		}
		// 移动否
		return move;
	}

	public void reborn() {
		dead = false;
		setX(original.x);
		setY(original.y);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * game.breeze.data.GameObject#writeTo(game.breeze.socket.util.ByteBuffer)
	 */
	@Override
	public void writeTo(ByteBuffer buffer) {
		buffer.writeInt(id);
		buffer.writeBoolean(dead);
		buffer.writeInt(getX());
		buffer.writeInt(getY());
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = -1155641194126227115L;

	/**
	 * @return the dead
	 */
	public boolean isDead() {
		return dead;
	}

	/**
	 * @param dead
	 *            the dead to set
	 */
	public void setDead(boolean dead) {
		this.dead = dead;
	}

	/**
	 * @return the monsterDef
	 */
	public MonsterDef getMonsterDef() {
		return monsterDef;
	}

	/**
	 * @param positions
	 *            the positions to set
	 */
	public void setPositions(List<Position> positions) {
		this.positions.addAll(positions);
		Position p = positions.get(0);
		this.original = p;
		setX(p.x);
		setY(p.y);
	}

	public void walk() {
		// 没有路可以走,重新设置目标点
		if (paths.size() == 0) {
			// 随机目的地
			int destIndex = RandomUtils.nextInt(positions.size());
			// 目的地
			Position dp = positions.get(destIndex);
			// 查找路径
			List<AStarNode> finds = mapController.findPath(getX(), getY(), dp.x, dp.y);
			// 添加移动路径
			paths.addAll(finds);
		}

		if (paths.size() <= 0) {
			return;
		}

		AStarNode node = paths.getLast();// path.pollLast();

		int dirX = node.getCol() * mapController.cellSize >= getX() ? 1 : -1;
		int dirY = node.getRow() * mapController.cellSize >= getY() ? 1 : -1;

		position.y += dirY * 2;
		position.x += dirX * 2;

		if (dirY == 1 && getY() >= node.getRow() * mapController.cellSize) {
			position.y = node.getRow() * mapController.cellSize;
		} else if (dirY == -1 && getY() <= node.getRow() * mapController.cellSize) {
			position.y = node.getRow() * mapController.cellSize;
		}

		if (dirX == 1 && getX() >= node.getCol() * mapController.cellSize) {
			position.x = node.getCol() * mapController.cellSize;
		} else if (dirX == -1 && getX() <= node.getCol() * mapController.cellSize) {
			position.x = node.getCol() * mapController.cellSize;
		}

		if (getY() == node.getRow() * mapController.cellSize && getX() == node.getCol() * mapController.cellSize) {
			paths.removeLast();
		}
	}
}
